package com.company.provider.controller;

import com.company.api.entity.Goods;
import com.company.provider.service.GoodsService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping("/goods")
public class GoodsController {

    private static final Logger logger = LoggerFactory.getLogger(GoodsController.class);

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private GoodsService goodsService;

    @GetMapping("/list")
    public List<Goods> getGoods() {
        return goodsService.getGoods();
    }

    /**
     * 注意：如果需要在dashboard中看到具体内容，需要调用下熔断的接口http://localhost:8001/goods/list/hystrix，否则访问
     * http://localhost:8001/hystrix.stream时，会一直显示PING，而无具体数据
     * //熔断器是用于服务端
     * //服务降级是用于客户端
     * //ribbon负载均衡时用于客户端的负载均衡（也即客户端自行决定调用哪台服务端进行负载均衡）
     * @return
     */
    @GetMapping("/list/hystrix")
    //一旦该方法抛出异常了，会自动调用HystrixCommand注解中制定的getGoodsHystrixFallBack方法作为返回值
    @HystrixCommand(fallbackMethod = "getGoodsHystrixFallBack")
    public List<Goods> getGoodsHystrix() {
        List<Goods> goods = goodsService.getGoods();

        //因为从数据库查询出来的记录大于0，这里故意让程序抛出异常，以验证熔断器功能
        if (goods.size() > 0) {
            throw new RuntimeException("查询出结果大于0！");
        }
        return goods;
    }

    /**
     * 验证熔断器功能
     * @return
     */
    public List<Goods> getGoodsHystrixFallBack() {
        logger.info("验证熔断器功能");
        return new ArrayList<>(Collections.singleton(new Goods("熔断器ID", "熔断器名称")));
    }

    /**
     * 服务发现，提供一个接口可以查询当前组件提供了哪些服务
     * @return
     */
    @GetMapping("/discovery")
    public Object discovery() {
        List<String> services = discoveryClient.getServices();
        System.out.println("discovery服务列表" + services);

        List<ServiceInstance> instances = discoveryClient.getInstances("microservicecloud-goods".toUpperCase());
        instances.forEach(x ->
                System.out.println("serviceId:" + x.getServiceId()
        + ",host:" + x.getHost()
        + ",port:" + x.getPort()
        + ",uri:" + x.getUri()));
        return discoveryClient;
    }
}
